/*************************************************************************
    > File Name: test_barrier.c
    > Author: Thinking
    > Mail: program_code@sohu.com
    > Created Time: Sat Sep 18 16:48:26 2021
 ************************************************************************/

#include <crt_util.h>
#include <stdio.h>

typedef struct myNode_s {
    _msg_q queue;
    int val;
} myNode_t;

void travel_queue(_msg_q* queue)
{
    _msg_q* q = NULL;
    for (q = _queue_head(queue); q != _queue_sentinel(queue); q = _queue_next(q)) {
        myNode_t* reqnode;
        reqnode = _queue_data(q, myNode_t, queue);
        printf("val:%d\n", reqnode->val);
    }
}

void test_msgq(void)
{
    _msgq_t msg;
    _msgq_init(&msg);

    _msgq_t msg1;
    _msgq_init(&msg1);

    myNode_t* regnode = malloc(sizeof(myNode_t));
    regnode->val = 1;

    myNode_t* regnode1 = malloc(sizeof(myNode_t));
    regnode1->val = 2;

    _msgq_produce(&msg, &regnode->queue);
    _msgq_produce(&msg, &regnode1->queue);

    // copy to msg1.queue
    _msgq_consume(&msg, &msg1.queue);

    // output
    travel_queue(&msg1.queue);
    travel_queue(&msg.queue);
}

void test_cjson(void)
{
    // const char* code = "{\"component\":1111111111111111111111}";
    const char* code = "{\"component\":1111111111111111111111}";
    // cJSON* jsRoot = cJSON_Parse(code);

    sjon* jsRoot = sjson_parse(code, 0, 1);
    sjon* json = sjson_get_obj(jsRoot, "component");
    sjon* jsDup = sjson_duplicate(jsRoot);

    char* buf1 = sjson_print(jsDup, 1024, 1);
    printf("%s\n", buf1);

    if (sjson_is_double(json) == S_SUCCESS) {
        printf("%d\n", 1);
    }

    sjon* jsCode1 = sjson_create_double(10.0001);
    sjon* jsCode2 = sjson_create_double(10.002);
    sjon* jsString = sjson_create_string("hello");

    sjson_add_obj(jsRoot, "jsCode1", jsCode1);
    sjson_add_obj(jsRoot, "jsCode2", jsCode2);
    sjson_add_obj(jsRoot, "jsString", jsString);

    if (sjson_is_double(jsCode1) == sjson_true) {
        // printf("%d\n", 2);
    }

    // char* buf = cJSON_Print(jsRoot, 1024, 0);
    char* buf = sjson_print(jsRoot, 1024, 0);
    printf("%s\n", buf);
    sjson_delete(jsRoot);
}

struct test_node {
    struct _rbtree_node node;
    uint64_t a;
};

struct test_node_root {
    struct _rbtree_root node;
    uint64_t a;
};

struct test_node* my_search(struct _rbtree_root* root, uint64_t a)
{
    struct _rbtree_node* node = root->rb_node;

    while (node) {
        struct test_node* data = _container_of(node, struct test_node, node);

        // int result = data->a == a ? 1 : 0;

        if (data->a < a)
            node = node->rb_left;
        else if (data->a > a)
            node = node->rb_right;
        else
            return data;
    }
    return NULL;
}

int my_insert(struct _rbtree_root* root, struct test_node* data)
{
    struct _rbtree_node** new = &(root->rb_node);
    struct _rbtree_node* parent = NULL;

    while (*new) {
        struct test_node* newnode = _container_of(*new, struct test_node, node);

        parent = *new;
        if (data->a < newnode->a)
            new = &((*new)->rb_left);
        else if (data->a > newnode->a)
            new = &((*new)->rb_right);
        else
            return FALSE;
    }

    rb_link_node(&data->node, parent, new);
    rb_insert_color(&data->node, root);

    return TRUE;
}

int test_rbtree(void)
{
    struct _rbtree_root treeroot = RB_ROOT;

    DWORD dwStart = GetTickCount();

    uint64_t uloop = 0;
    for (uloop = 1; uloop < 13; uloop++) {
        struct test_node* node = NULL;
        node = heap_malloc(sizeof(struct test_node));
        node->a = uloop;
        my_insert(&treeroot, node);
    }
    DWORD dwEnd = GetTickCount();

    DWORD dwDiff = dwEnd - dwStart;

    // rbtree_node insert 19766
    // printf("rbtree_node insert %lu\n", dwDiff);

    dwStart = GetTickCount();

    for (uloop = 0; uloop < 20; uloop++) {
        struct _rbtree_node* node = rb_first(&treeroot);
        struct test_node* newnode = _container_of(node, struct test_node, node);
        rb_erase(node, &treeroot);

        heap_free(newnode);
    }

    dwEnd = GetTickCount();

    dwDiff = dwEnd - dwStart;

    // rbtree_node remove 10093
    // printf("rbtree_node remove %lu\n", dwDiff);

    return S_SUCCESS;
}

struct test_mini_heap_node {
    _heap_node_t timer;
    uint64_t timeout;
    uint64_t start_id;
};

struct test_mini_heap {
    _heap_t timer_heap;
};

static _heap_t* timer_heap(const struct test_mini_heap* loop)
{
    return (_heap_t*)&loop->timer_heap;
}

static int timer_less_than(const _heap_node_t* ha, const _heap_node_t* hb)
{
    const struct test_mini_heap_node* a;
    const struct test_mini_heap_node* b;

    a = _container_of(ha, struct test_mini_heap_node, timer);
    b = _container_of(hb, struct test_mini_heap_node, timer);

    if (a->timeout < b->timeout)
        return 1;

    if (b->timeout < a->timeout)
        return 0;

    return a->start_id < b->start_id;
}

int mini_heap(void)
{
    struct test_mini_heap heap;
    struct test_mini_heap_node node1;
    node1.timeout = 1;

    // struct test_mini_heap_node node2;

    // node2.timeout = 2;

    // struct test_mini_heap_node node3;

    // node3.timeout = 2;

    // struct test_mini_heap_node node4;

    // node4.timeout = 4;

    heap_init(&heap.timer_heap);

    heap_insert(timer_heap(&heap), (_heap_node_t*)&node1.timer, timer_less_than);

    //_minheap_insert(timer_heap(&heap),
    //	(_minheap_node_t*) &node2.timer, timer_less_than);

    //_minheap_insert(timer_heap(&heap),
    //	(_minheap_node_t*) &node3.timer, timer_less_than);

    DWORD dwStart = GetTickCount();

    uint64_t uloop = 0;

    for (uloop = 0; uloop < 20000000; uloop++) {
        struct test_mini_heap_node* node = NULL;

        node = heap_malloc(sizeof(struct test_mini_heap_node));

        node->timeout = uloop;
        heap_insert(timer_heap(&heap), (_heap_node_t*)&node->timer, timer_less_than);
    }

    DWORD dwEnd = GetTickCount();

    DWORD dwDiff = dwEnd - dwStart;
    // min_heap insert 9954
    // printf("min_heap insert %lu\n", dwDiff);

    dwStart = GetTickCount();
    for (uloop = 0; uloop < 20000000; uloop++) {
        heap_dequeue(timer_heap(&heap), timer_less_than);
    }
    dwEnd = GetTickCount();

    dwDiff = dwEnd - dwStart;

    // min_heap remove 55078
    // printf("min_heap remove %lu\n", dwDiff);

    //_minheap_remove(timer_heap(&heap),
    //	(_minheap_node_t*) &node2.timer, timer_less_than);

    // const struct test_mini_heap_node* a;
    //_minheap_node_t* p = _minheap_root(timer_heap(&heap));
    // a = _container_of(p, struct test_mini_heap_node, timer);
    //_minheap_dequeue(timer_heap(&heap), timer_less_than);

    // p = _minheap_root(timer_heap(&heap));
    // a = _container_of(p, struct test_mini_heap_node, timer);
    //_minheap_dequeue(timer_heap(&heap), timer_less_than);

    // p = _minheap_root(timer_heap(&heap));
    // a = _container_of(p, struct test_mini_heap_node, timer);
    //_minheap_dequeue(timer_heap(&heap), timer_less_than);

    // p = _minheap_root(timer_heap(&heap));
    // a = _container_of(p, struct test_mini_heap_node, timer);
    //_minheap_dequeue(timer_heap(&heap), timer_less_than);

    return S_SUCCESS;
}

int stdtest_func(void)
{
    uint64 largeNumber = 0;
    // largeNumber = 9876543210;

    largeNumber = 76543210;
    uint32 smallNumber = 0;
    smallNumber = largeNumber & UINT32_MAX;

    uint64touint32(largeNumber, &smallNumber);

    return S_SUCCESS;
}

unsigned char* str2hex(char* str)
{
    unsigned char* ret = NULL;
    size_t str_len = s_strlen(str);
    int i = 0;
    assert((str_len % 2) == 0);
    ret = (unsigned char*)malloc(str_len / 2);
    for (i = 0; i < str_len; i = i + 2) {
        sscanf(str + i, "%2hhx", &ret[i / 2]);
    }
    return ret;
}
char* padding_buf(char* buf, int size, int* final_size)
{
    char* ret = NULL;
    int pidding_size = aes_block_size - (size % aes_block_size);
    int i;
    *final_size = size + pidding_size;
    ret = (char*)malloc(size + pidding_size);
    memcpy(ret, buf, size);
    if (pidding_size != 0) {
        for (i = size; i < (size + pidding_size); i++) {
            ret[i] = 0;
        }
    }
    return ret;
}
void printf_buff(char* buff, int size)
{
    int i = 0;
    for (i = 0; i < size; i++) {
        printf("%02X ", (unsigned char)buff[i]);
        if ((i + 1) % 8 == 0) {
            printf("\n");
        }
    }
    printf("\n\n\n\n");
}
void encrpyt_buf(char* raw_buf, char** encrpy_buf, int len)
{
    aes_ctx_t aes;
    unsigned char* key = str2hex("8cc72b05705d5c46f412af8cbed55aad");
    unsigned char* iv = str2hex("667b02a85c61c786def4521b060265e8");
    _aes_set_encrypt_key(key, 128, &aes);
    _aes_encrypt(raw_buf, *encrpy_buf, &aes);
    free(key);
    free(iv);
}
void decrpyt_buf(char* raw_buf, char** encrpy_buf, int len)
{
    aes_ctx_t aes;
    unsigned char* key = str2hex("8cc72b05705d5c46f412af8cbed55aad");
    unsigned char* iv = str2hex("667b02a85c61c786def4521b060265e8");
    _aes_set_decrypt_key(key, 128, &aes);
    _aes_decrypt(raw_buf, *encrpy_buf, &aes);
    free(key);
    free(iv);
}

void test_ace(void)
{
    char* raw_buf = NULL;
    char* after_padding_buf = NULL;
    int padding_size = 0;
    char* encrypt_buf = NULL;
    char* decrypt_buf = NULL;

    // 1
    raw_buf = (char*)malloc(17);
    memcpy(raw_buf, "life's a struggle", 17);
    printf("------------------raw_buf\n");
    printf_buff(raw_buf, 17);

    // 2
    after_padding_buf = padding_buf(raw_buf, 17, &padding_size);
    printf("------------------after_padding_buf\n");
    printf_buff(after_padding_buf, padding_size);

    // 3
    encrypt_buf = (char*)malloc(padding_size);
    encrpyt_buf(after_padding_buf, &encrypt_buf, padding_size);
    printf("------------------encrypt_buf\n");
    printf_buff(encrypt_buf, padding_size);

    // 4
    decrypt_buf = (char*)calloc(sizeof(char), padding_size);
    decrpyt_buf(encrypt_buf, &decrypt_buf, padding_size);
    printf("------------------decrypt_buf\n");
    printf_buff(decrypt_buf, padding_size);

    free(raw_buf);
    free(after_padding_buf);
    free(encrypt_buf);
    free(decrypt_buf);
}

void test_stdlib()
{
    // test_rbtree();
    // stdtest_func();
    // mini_heap();
    // test_rbtree();
}


void test_array()
{
 
}